package org.devio.simple;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.fraction.FractionAbility;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.app.Environment;
import ohos.utils.net.Uri;
import org.devio.takephoto.ResourceTable;
import org.devio.takephoto.app.TakePhoto;
import org.devio.takephoto.compress.CompressConfig;
import org.devio.takephoto.model.CropOptions;
import org.devio.takephoto.model.LubanOptions;
import org.devio.takephoto.model.TakePhotoOptions;
import org.devio.takephoto.uitl.ResUtil;
import org.devio.takephoto.uitl.TConstant;
import org.devio.takephoto.uitl.UiUtil;

import java.io.File;

public class CustomHelper {
    private static final String TAG = CustomHelper.class.getSimpleName();
    private Component rootView;
    private RadioButton rbCropYes, rbPickWithOwn, rbCorrectYes, rbCompressYes, rbFile, rbCompressWithOwn, rbCropOwn, rbAspect, rbRawYes, rbShowYes;
    private TextField etCropHeight, etCropWidth, etLimit, etSize, etHeightPx;
    private Ability mContext;

    public static CustomHelper of(Component rootView, Ability context) {
        return new CustomHelper(rootView, context);
    }

    private CustomHelper(Component rootView, Ability context) {
        this.rootView = rootView;
        mContext = context;
        init();
    }

    /**
     * This method is used to init the child views
     */
    private void init() {
        ScrollView scrollView = (ScrollView) rootView.findComponentById(ResourceTable.Id_scroll_parent);
        if (mContext instanceof FractionAbility) {
            ShapeElement rectShape = new ShapeElement();
            rectShape.setShape(ShapeElement.RECTANGLE);
            rectShape.setRgbColor(RgbColor.fromArgbInt(ResUtil.getColor(mContext, ResourceTable.Color_lighter_gray)));
            scrollView.setBackground(rectShape);
        }
        etCropHeight = (TextField) rootView.findComponentById(ResourceTable.Id_etCropHeight);
        etCropHeight.setBasement(UiUtil.getLineShape(mContext, 5, ResourceTable.Color_color_gray));
        etCropWidth = (TextField) rootView.findComponentById(ResourceTable.Id_etCropWidth);
        etCropWidth.setBasement(UiUtil.getLineShape(mContext, 5, ResourceTable.Color_color_gray));
        etLimit = (TextField) rootView.findComponentById(ResourceTable.Id_etLimit);
        etLimit.setBasement(UiUtil.getLineShape(mContext, 2, ResourceTable.Color_color_gray));
        etSize = (TextField) rootView.findComponentById(ResourceTable.Id_etSize);
        etSize.setBasement(UiUtil.getLineShape(mContext, 7, ResourceTable.Color_color_gray));
        etHeightPx = (TextField) rootView.findComponentById(ResourceTable.Id_etHeightPx);
        etHeightPx.setBasement(UiUtil.getLineShape(mContext, 5, ResourceTable.Color_color_gray));
        TextField etWidthPx = (TextField) rootView.findComponentById(ResourceTable.Id_etWidthPx);
        etWidthPx.setBasement(UiUtil.getLineShape(mContext, 5, ResourceTable.Color_color_gray));
        prepareRadioButton();
    }

    /**
     * This method is used to prepare radio button with their background resources
     */
    private void prepareRadioButton() {
        rbCropYes = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCropYes);
        setRadioButtonElement(rbCropYes);
        rbCropYes.setChecked(true);
        RadioButton rbCropNo = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCropNo);
        setUncheckedCheckbox(rbCropNo);
        rbCropNo.setChecked(false);
        setRadioButtonElement(rbCropNo);
        RadioButton rbCropByOther = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCropByOther);
        setRadioButtonElement(rbCropByOther);
        rbCropByOther.setChecked(true);
        rbCropOwn = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCropOwn);
        setUncheckedCheckbox(rbCropOwn);
        rbCropOwn.setChecked(false);
        setRadioButtonElement(rbCropOwn);
        RadioButton rbOutPut = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbOutPut);
        setRadioButtonElement(rbOutPut);
        rbOutPut.setChecked(true);
        rbAspect = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbAspect);
        setUncheckedCheckbox(rbAspect);
        rbAspect.setChecked(false);
        setRadioButtonElement(rbAspect);
        rbCompressWithOwn = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCompressWithOwn);
        setRadioButtonElement(rbCompressWithOwn);
        rbCompressWithOwn.setChecked(true);
        RadioButton rbCompressWithLuban = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCompressWithLuban);
        setUncheckedCheckbox(rbCompressWithLuban);
        rbCompressWithLuban.setChecked(false);
        setRadioButtonElement(rbCompressWithLuban);
        rbCompressYes = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCompressYes);
        setRadioButtonElement(rbCompressYes);
        rbCompressYes.setChecked(true);
        RadioButton rbCompressNo = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCompressNo);
        setUncheckedCheckbox(rbCompressNo);
        rbCompressNo.setChecked(false);
        setRadioButtonElement(rbCompressNo);
        rbShowYes = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbShowYes);
        setRadioButtonElement(rbShowYes);
        rbShowYes.setChecked(true);
        RadioButton rbShowNo = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbShowNo);
        setUncheckedCheckbox(rbShowNo);
        rbShowNo.setChecked(false);
        setRadioButtonElement(rbShowNo);
        rbPickWithOwn = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbPickWithOwn);
        setRadioButtonElement(rbPickWithOwn);
        rbPickWithOwn.setChecked(true);
        RadioButton rbPickWithOther = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbPickWithOther);
        setUncheckedCheckbox(rbPickWithOther);
        rbPickWithOther.setChecked(false);
        setRadioButtonElement(rbPickWithOther);
        RadioButton rbGallery = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbGallery);
        setRadioButtonElement(rbGallery);
        rbGallery.setChecked(true);
        rbFile = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbFile);
        setUncheckedCheckbox(rbFile);
        rbFile.setChecked(false);
        setRadioButtonElement(rbFile);
        rbCorrectYes = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCorrectYes);
        setRadioButtonElement(rbCorrectYes);
        rbCorrectYes.setChecked(true);
        RadioButton rbCorrectNo = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbCorrectNo);
        setUncheckedCheckbox(rbCorrectNo);
        rbCorrectNo.setChecked(false);
        setRadioButtonElement(rbCorrectNo);
        rbRawYes = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbRawYes);
        setRadioButtonElement(rbRawYes);
        rbRawYes.setChecked(true);
        RadioButton rbRawNo = (RadioButton) rootView.findComponentById(ResourceTable.Id_rbRawNo);
        setUncheckedCheckbox(rbRawNo);
        rbRawNo.setChecked(false);
        setRadioButtonElement(rbRawNo);
    }

    /**
     * This method is used to change the media resource of radio button
     *
     * @param radioButton RadioButton
     */
    private void setRadioButtonElement(RadioButton radioButton) {
        radioButton.setCheckedStateChangedListener(new RadioButton.CheckedStateChangedListener() {
            @Override
            public void onCheckedChanged(AbsButton absButton, boolean isChecked) {
                if (radioButton.isChecked()) {
                    radioButton.setButtonElement(ResUtil.getPixelMapDrawable(mContext, ResourceTable.Media_radio_checked));
                } else {
                    radioButton.setButtonElement(ResUtil.getPixelMapDrawable(mContext, ResourceTable.Media_radio_unchecked));
                }
            }
        });
    }

    /**
     * This method is used to set unchecked radiobutton background
     *
     * @param radioButton RadioButton
     */
    private void setUncheckedCheckbox(RadioButton radioButton) {
        radioButton.setButtonElement(ResUtil.getPixelMapDrawable(mContext, ResourceTable.Media_radio_unchecked));
    }

    /**
     * This method is used to handle click event
     *
     * @param view      click component
     * @param takePhoto takephoto object to handle all operations
     */
    public void onClick(Component view, TakePhoto takePhoto) {
        File file = new File(mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES), System.currentTimeMillis() + ".jpg");
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }

        Uri imageUri = Uri.getUriFromFile(file);
        configCompress(takePhoto);
        configTakePhotoOption(takePhoto);
        switch (view.getId()) {
            case ResourceTable.Id_btnPickBySelect:
                int limit = Integer.parseInt(etLimit.getText());
                if (limit > 1) {
                    if (rbCropYes.isChecked()) {
                        takePhoto.onPickMultipleWithCrop(limit, getCropOptions());
                    } else {
                        takePhoto.onPickMultiple(limit);
                    }
                    return;
                }
                if (rbFile.isChecked()) {
                    if (rbCropYes.isChecked()) {
                        takePhoto.onPickFromDocumentsWithCrop(imageUri, getCropOptions());
                    } else {
                        takePhoto.onPickFromDocuments();
                    }
                    return;
                } else {
                    if (rbCropYes.isChecked()) {
                        takePhoto.onPickFromGalleryWithCrop(imageUri, getCropOptions());
                    } else {
                        takePhoto.onPickFromGallery();
                    }
                }
                break;
            case ResourceTable.Id_btnPickByTake:
                launchCamera();
                break;
            default:
                break;
        }
    }

    /**
     * This method is used to launch camera ability
     */
    private void launchCamera() {
        Operation operationBuilder = new Intent.OperationBuilder()
                .withBundleName(TConstant.APP_BUNDLE_NAME)
                .withAbilityName(CameraAbility.class.getSimpleName())
                .build();
        Intent intent = new Intent();
        intent.setOperation(operationBuilder);
        mContext.startAbilityForResult(intent, TConstant.RC_PICK_PICTURE_FROM_CAPTURE);
    }

    /**
     * This method is used to manage take photo options
     *
     * @param takePhoto to set takephoto options
     */
    private void configTakePhotoOption(TakePhoto takePhoto) {
        TakePhotoOptions.Builder builder = new TakePhotoOptions.Builder();
        if (rbPickWithOwn.isChecked()) {
            builder.setWithOwnGallery(true);
        }
        if (rbCorrectYes.isChecked()) {
            builder.setCorrectImage(true);
        }
        takePhoto.setTakePhotoOptions(builder.create());
    }

    /**
     * This method is used to change compression configuration
     *
     * @param takePhoto to set takephoto compression options
     */
    private void configCompress(TakePhoto takePhoto) {
        if (!rbCompressYes.isChecked()) {
            takePhoto.onEnableCompress(null, false);
            return;
        }
        int maxSize = Integer.parseInt(etSize.getText());
        int width = Integer.parseInt(etCropWidth.getText());
        int height = Integer.parseInt(etHeightPx.getText());
        boolean showProgressBar = rbShowYes.isChecked();
        boolean enableRawFile = rbRawYes.isChecked();
        CompressConfig config;
        if (rbCompressWithOwn.isChecked()) {
            config = new CompressConfig.Builder().setMaxSize(maxSize)
                    .setMaxPixel(Math.max(width, height))
                    .enableReserveRaw(enableRawFile)
                    .create();
        } else {
            LubanOptions option = new LubanOptions.Builder().setMaxHeight(height).setMaxWidth(width).setMaxSize(maxSize).create();
            config = CompressConfig.ofLuban(option);
            config.enableReserveRaw(enableRawFile);
        }
        takePhoto.onEnableCompress(config, showProgressBar);
    }

    /**
     * This method is used get crop option
     *
     * @return CropOptions with multiple aspect values
     */
    private CropOptions getCropOptions() {
        if (rbCropYes.isChecked()) {
            return null;
        }
        int height = Integer.parseInt(etCropHeight.getText());
        int width = Integer.parseInt(etCropWidth.getText());
        boolean withWonCrop = rbCropOwn.isChecked();

        CropOptions.Builder builder = new CropOptions.Builder();

        if (rbAspect.isChecked()) {
            builder.setAspectX(width).setAspectY(height);
        } else {
            builder.setOutputX(width).setOutputY(height);
        }
        builder.setWithOwnCrop(withWonCrop);
        return builder.create();
    }
}
